package org.example;

import cn.hutool.core.codec.Base64;
import cn.hutool.json.JSONUtil;
import org.example.Client.Avatar;
import org.example.Client.extend;
import org.example.Client.subtitleExtend;
import org.example.service.AvatarToken;
import org.example.service.WSUtil;


import javax.websocket.ContainerProvider;

import javax.websocket.WebSocketContainer;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.CompletableFuture;

public class WebsocketClient2 {
    public static String appid = "xxxxxxxx"; //申请的appid
    public static String appSercet = "xxxxxxxxxxxxxxxxxxxxxxxx"; //appid对应的key
    public static String vcn = "xxxxxxxxxxxxxxxx";//发音人id
    public static String anchorId = "xxxxxxxx";//形象id
    public static String version = "v1";
    public static String token_url = "https://avatar-hci.xfyousheng.com/v1/token";//公网地址
    public static String ws_url = "wss://avatarws.xfyousheng.com/v1/link";//公网交互地址


    public static void main(String[] args) {
        try {
            //获取token
            AvatarToken at = new AvatarToken();
            String token = at.getToken2(token_url, appid, appSercet);
            System.out.println("token:" + token);
            if (token.isEmpty()) {
                System.out.println("get token error");
                return;
            }
            String str = "token=" + token + "&anchorId=" + anchorId + "&appid=" + appid;

            System.out.println("ws_url+signa=:" + ws_url + "?signa=" + Base64.encode(str));
            WSUtil client = new WSUtil(ws_url+"?signa=" + Base64.encode(str.getBytes()));
            //初始化虚拟人
            client.send(Init(token));
            //每5秒发送一次心跳,用来维护websocket连接，10秒内没有ping-pong，则自动断连
            Timer timer = new Timer();
            Avatar avatarping = new Avatar();
            avatarping.setType("-99");
            CompletableFuture.runAsync(() -> {
                TimerTask timeoutTask = new TimerTask() {
                    @Override
                    public void run() {
                        client.send(JSONUtil.toJsonStr(avatarping));
                    }
                };
                timer.scheduleAtFixedRate(timeoutTask, 0, 5000);
                System.out.println("进入定时器内部");
            });
            //可以先使用webrtc协议（pushMode=6）播放，启动后返回信息中有httpsUrl,例如：webrtc://srs-stream.cn-huadong-1.xf-yun.com:9850/live/24a589b3-7bd0-3153-db49-de5a5871a301?stream=24a589b3-7bd0-3153-db49-de5a5871a301&schema=https
            //复制下发的该地址，到网址：https://ossrs.net/players/rtc_player.html，进行拉流播放
            //这里停顿10秒是为了给复制推流地址到网址拉流播放的操作时间。实际等服务端返回首帧回调type=100就可以拉流播放了
            Thread.sleep(10000);



            //文本驱动，文本中参杂动作指令[[action=动作标签]]
            String sid = UUID.randomUUID().toString();
            client.send(TextDriver("科大讯飞股份有限公司成立于1999年，是亚太地区知名的智能语音和人工智能上市企业[[action=A_RH_like_O]]，"));
            client.send(TextDriver("公司总部在合肥。科大讯飞股份有限公司是一家专业从事智能语音及语音技术研究[[action=A_RH_good_O]]、"));
            client.send(TextDriver("软件及芯片产品开发、语音信息服务的软件企业。自成立以来[[action=A_RH_encourage_O]]，"));
            client.send(TextDriver("一直从事智能语音、自然语言理解、计算机视觉等核心技术研究并保持了国际前沿技术水平；积极推动人工智能产品和行业应用落地，致力让机器“能听会说，能理解会思考”"));
            client.send(TextDriver("用人工智能建设美好世界。2016年，发布讯飞翻译机，开创智能消费的新品类，2022年，科大讯飞发起“讯飞超脑2030”计划，旨在让人工智能懂知识、善学习、能进化，让机器人走进每个家庭。"));
            client.send(TextDriver("2021年，科大讯飞“语音识别方法及系统”发明专利荣获第二十二届中国专利金奖，这也是国内知识产权领域的最高奖项"));

            //文本交互
//            client.send(TextNlp("介绍下科大讯飞虚拟人"));

            //音频交互
            //音频驱动，不会进行理解，直接播报音频中的内容，只进行口唇匹配
            //发送音频驱动前需先发送一个打断type=-1，用来打断当前正在播报的内容
            //一个音频中status参数值是：0-1-1-1-……-1-1-1-2。从0开始，1过渡，2结束。
            //byte数组字节数不要太少，否则会有卡顿的感觉
            //Thread.sleep(100)这里是为了模拟间隔，最好间隔40-100ms
          try(InputStream inputStream = Files.newInputStream(Paths.get("src/main/resources/fulldepxtest.pcm"))) {
                byte[] bytes = new byte[1024*50];
                int len;
                int status = 0;
                String requestId = UUID.randomUUID().toString();
                while ((len = inputStream.read(bytes)) != -1) {
                    System.out.println("len="+len);
                    if(len != 1024*50){
                        status = 2;
                    }
                    System.out.println("status="+status);
                    Thread.sleep(400);
                    String audioData = Base64.encode(Arrays.copyOfRange(bytes, 0, len));
                    //这里AudioNlp改成AudioDriverFirst就是音频交互
                    client.send(AudioNlp(requestId,status, audioData));
                    Arrays.fill(bytes, (byte) 0);
                    status = 1;
                }
            }catch (Exception e){
                e.printStackTrace();
            }

                //驱动动作,index是时间点，计算方式是 采样率乘以时间，若16K且10秒后触发就是：32000*10，若24K且10秒后触发就是：48000*10，传0就是立即触发做动作
//                System.out.println("发送动作");
//                client.send(ActionDriver("[{\"type\":\"A_RLH_emphasize_O\",\"index\":0}]"));
//                Thread.sleep(4000);
//                client.send(ActionDriver("[{\"type\":\"A_R_introduced_O\",\"index\":0}]"));
//                Thread.sleep(4000);
//                client.send(ActionDriver("[{\"type\":\"A_RH_hello_O\",\"index\":0}]"));

            Thread.sleep(10000);

            //关闭连接，使用的是websocket本身的close
//            client.close();
//            timer.cancel();
//            System.out.println("关闭websocket");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }



    //初始化虚拟人type=0
    public static String Init(String token) {
        Avatar avatarinit = new Avatar();
        extend extend = new extend();
        subtitleExtend subtitleExtend = new subtitleExtend();
        avatarinit.setType("0");//协议类型，type=0为初始化
//        avatarinit.setBgType(0);//背景图，0：图片，1：视频
//        avatarinit.setBgUrl("");//背景图可访问到的url地址，不传则为绿幕
        avatarinit.setHeight(1920);//虚拟人分辨率，像素值，必须是4的倍数
        avatarinit.setWidth(1080);//虚拟人分辨率，像素值，必须是4的倍数
        avatarinit.setVcn(vcn);//appid授权的发音人id
        avatarinit.setCustomerInterrupt(false);//交互模式，false为打断模式，true为追加模式
        avatarinit.setPushMode(6);//视频流协议类型，type=0为rtmp、type=6为webrtc、type=12为xrtc，仅xrtc支持透明背景
        avatarinit.setSubtitle(true);//是否开启字幕。

        //拓展参数
//        extend.setAlpha(false);//是否开启透明背景，仅xrtc协议支持需配合type=12
//        extend.setPitch("50");//音调，默认50
//        extend.setVol("100");//音量
//        extend.setSpd("50");//语速，默认50
//        extend.setBitrate("10000000");//视频码率，取值范围：2000 - 20000000，码率越大越清晰，同时对网络要求越高
//        extend.setAlpha(true);//是否开启透明背景，只有xrtc协议支持，需要同时使用xrtc协议且此处传true

        //字幕参数
//        subtitleExtend.setFontColor("#00FF00");
//        subtitleExtend.setFontSize("87");//字体大小，取直范围：1-87
//        subtitleExtend.setxLocation("300");//字幕左右平移
//        subtitleExtend.setyLocation("300");//字幕上下平移

        //拓展、字幕参数放到根节点
        avatarinit.setExtend(extend);
        avatarinit.setSubtitleExtend(subtitleExtend);

        return JSONUtil.toJsonStr(avatarinit);
    }

    //打断协议type=-1，发送打断后不可以再发送上一段的数据，否则会导致session不一致，虚拟人可能崩溃
    //例如已发送打断后还在发送上一段的音频驱动数据，就会导致session不一致。
    public static String Reset(){
        Avatar avatarReset = new Avatar();
        avatarReset.setType("-1");
        return JSONUtil.toJsonStr(avatarReset);
    }

    //语音交互type=1
    public static String AudioNlp(String requestId, int status,String AudioData) {
        Avatar avatarAudioNlp = new Avatar();
        avatarAudioNlp.setType("1");
        avatarAudioNlp.setSid("vdh00081505@hu196e7614b4c0441882");
        avatarAudioNlp.setFrameStatus(status);
        avatarAudioNlp.setData(AudioData);
        avatarAudioNlp.setFullDuplex(true);
        avatarAudioNlp.setCid(requestId);
        return JSONUtil.toJsonStr(avatarAudioNlp);
    }

    //文本交互type=2
    public static String TextNlp(String Text) {
        Avatar avatarTextNlp = new Avatar();
        avatarTextNlp.setType("2");
        avatarTextNlp.setData(Base64.encode(Text));
        return JSONUtil.toJsonStr(avatarTextNlp);
    }

    //文本驱动type=3
    public static String TextDriver(String Text) {
        Avatar avatarTextDriver = new Avatar();
        avatarTextDriver.setType("3");
        avatarTextDriver.setSid(UUID.randomUUID().toString());
        avatarTextDriver.setCid(UUID.randomUUID().toString());
        avatarTextDriver.setData(Base64.encode(Text));
        avatarTextDriver.setFrameStatus(2);
        avatarTextDriver.setCustomerInterrupt(false);
        return JSONUtil.toJsonStr(avatarTextDriver);
    }

    //音频驱动type=4
    //不会进行理解，直接播报音频中的内容，只进行口唇匹配
    //发送音频驱动前需先发送一个打断type=-1，用来打断当前正在播报的内容
    //一个音频中Framestatus参数值是：0-1-1-1-……-1-1-1-2。从0开始，1过渡，2结束。
    public static String AudioDriverFirst(String requestId, int FrameStatus, String AudioByte) {
        Avatar avatarAudioDriverFirst = new Avatar();
        avatarAudioDriverFirst.setType("4");
        avatarAudioDriverFirst.setSid("vdh00081505@hu196e7614b4c0441882");
        avatarAudioDriverFirst.setFrameStatus(FrameStatus);
        avatarAudioDriverFirst.setData(AudioByte);
        avatarAudioDriverFirst.setCid(requestId);
        avatarAudioDriverFirst.setCustomerInterrupt(true);
        return JSONUtil.toJsonStr(avatarAudioDriverFirst);
    }

    //单独驱动动作type=6
    public static String ActionDriver(String Action) {
        Avatar avatarActionDriver = new Avatar();
        avatarActionDriver.setType("6");
        avatarActionDriver.setData(Base64.encode(Action));
        return JSONUtil.toJsonStr(avatarActionDriver);
    }

}
